package expressions;

import values.Boolean;
import values.Integer;
import values.Value;
import base.AST;
import base.Environment;
import base.Interpreter;

public class Equal implements Expression {

	private AST son1;
	private AST son2;

	/**
	 * Creates an expression that represents eval(son1) == eval(son2)
	 * 
	 * @param son1
	 *            a Value or an Expression
	 * @param son2
	 *            a Value or an Expression
	 */

	public Equal(AST son1, AST son2) {
		assert son1 instanceof Value || son1 instanceof Expression;
		assert son2 instanceof Value || son2 instanceof Expression;
		this.son1 = son1;
		this.son2 = son2;
	}

	/**
	 * Returns eval(son1) == eval(son2) if eval(son1) and eval(son2) are both
	 * integers or both booleans. Throws a BadExpressionValueException
	 * otherwise.
	 * 
	 * @throws BadExpressionException
	 */

	public Value eval(Environment env) throws BadExpressionException {

		try {
			Integer a = Interpreter.getInt(this.son1, env);
			Integer b = Interpreter.getInt(this.son2, env);

			if (a != null && b != null)
				return new Boolean(a.eval() == b.eval());

		} catch (BadExpressionException e) {

			Boolean c = Interpreter.getBoolean(this.son1, env);
			Boolean d = Interpreter.getBoolean(this.son2, env);

			if (c != null && d != null)
				return new Boolean(c.eval() == d.eval());
		}
		
		throw new BadExpressionException(
				"Trying to compare (equals) non-integer and non-boolean values");
	}

}
